﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using TableProto;
using WCBG.ToolsForUnity.Tools;
using WCBG.ToolsForUnity.Extension;
using DG.Tweening;

/// <summary>
/// 英语颜色 涂色游戏
/// </summary>
public class FillColorGameWindow : SingletonBaseWindow<FillColorGameWindow>
{

    #region ui property

    public Button _Btn_Return { get; set; }
    public Button _Btn_LoudSpeaker { get; set; }
    public RectTransform _Brush { get; set; }
    public RectTransform _BrushAllBG { get; set; }
    public RawImage _BrushColor { get; set; }
    public RawImage _FillTexture { get; set; }
    public RawImage _ColorImage1 { get; set; }
    public RawImage _ColorImage2 { get; set; }
    public Transform _ReadPanel { get; set; }
    public Transform _WordShowPanel { get; set; }
    public Text _WordText { get; set; }
    public Image _LULetter { get; set; }
    public Text _BTText { get; set; }
    public Transform _Effect_Suc { get; set; }


    #endregion

    private const string TEXTURE_BASE_PATH = EnglishColoursPath.englishColorTexturePath;
    private const int CHECK_FILL_TIME = 3;


    private Vector2 m_fillTextureStartPos;
    private Vector2 m_brushStartPos;
    private Vector2 m_originPoint;
    private Vector3 m_prevousBrushPoint;
    private Vector3 m_dragOffset;
    private Texture2D m_fillTex;
    private Texture2D m_drawTex;
    private Texture2D m_brushTex;
    private Color m_fillColor;
    private int halfBrushTexWidth;
    private int halfBrushTexHeight;
    private float checkAddTime;
    private bool isLockInput;
    private bool isGamePlaying;
    private bool isBrushing;
    private bool isStartDragBrush;
    private bool isSpeakerRepeat;
    private GameAudioSource m_brushAudio;

    private int currentTotalPixelNeedToFill;

    private EnglishColoursInfo m_info;
    private System.Action<bool> completeCallback;
    private System.Action onFillCompleteCallback;

    private bool[,] m_drawInfo;
    private bool[,] m_brushInfo;

    protected override void OnOpen(params object[] paramArray)
    {
        m_brushTex = _BrushColor.texture as Texture2D;
        m_fillTextureStartPos = _FillTexture.rectTransform.anchoredPosition;
        m_brushStartPos = _Brush.anchoredPosition;
        _Brush.gameObject.SetActive(false);
        _FillTexture.gameObject.SetActive(false);
        _ColorImage1.gameObject.SetActive(false);
        _ColorImage2.gameObject.SetActive(false);
        _ReadPanel.SetActive(false);
        _WordShowPanel.SetActive(false);
        _Effect_Suc.SetActive(false);

        halfBrushTexWidth = m_brushTex.width / 2;
        halfBrushTexHeight = m_brushTex.height / 2;

        int width = m_brushTex.width;
        int height = m_brushTex.height;
        m_brushInfo = new bool[width, height];
        for (int i = 0; i < width; i++)
        {
            for (int j = 0; j < height; j++)
            {
                Color col = m_brushTex.GetPixel(i, j);
                m_brushInfo[i, j] = col.a > 0.2f;
            }
        }
    }

    protected override void OnUpdate()
    {
        base.OnUpdate();

        if (isGamePlaying)
        {
            checkAddTime += Time.deltaTime;
            if (checkAddTime > CHECK_FILL_TIME)
            {
                checkAddTime = 0;
                CheckIsFillAll();
            }
        }
    }

    protected override void OnClose()
    {

    }

    protected override void AddListeners()
    {
        _Btn_Return.onClick.AddListener(OnButtonReturnClick);
        _Btn_LoudSpeaker.onClick.AddListener(OnButtonLoudSpeakerClick);
        FEasyInput.AddEvent(EEasyInputType.OnDown, OnDown);
        FEasyInput.AddEvent(EEasyInputType.OnHover, OnHover);
        FEasyInput.AddEvent(EEasyInputType.OnUp, OnUp);
        _BrushAllBG.AddComponentEx<UIInputHandler>().OnDown += OnBrushDown;
    }

    protected override void RemoveListensers()
    {
        _Btn_Return.onClick.RemoveAllListeners();
        _Btn_LoudSpeaker.onClick.RemoveAllListeners();
        FEasyInput.RemoveEvent(EEasyInputType.OnDown, OnDown);
        FEasyInput.RemoveEvent(EEasyInputType.OnHover, OnHover);
        FEasyInput.RemoveEvent(EEasyInputType.OnUp, OnUp);
        _BrushAllBG.AddComponentEx<UIInputHandler>().OnDown -= OnBrushDown;
    }


    private void OnDown()
    {
        //Vector3 to = FUGUITool.ScreenPointToUGUIPoint(WindowManager.Instance.canvas, Input.mousePosition);
        //_Brush.position = to;
        //m_prevousBrushPoint = _Brush.position;
    }

    private void OnHover()
    {
        if (!isStartDragBrush)
            return;
        Vector3 mousePos = Input.mousePosition;
        bool isOnDragArea = mousePos.x >= Screen.width * .06f && mousePos.x < Screen.width * (1 - .06f) && mousePos.y >= Screen.height * .12f && mousePos.y < Screen.height * (1 - .12f);
        if (!isOnDragArea) return;

        Vector3 to = FUGUITool.ScreenPointToUGUIPoint(WindowManager.Instance.canvas, mousePos);
        Vector3 brushPos = to + m_dragOffset;
        _Brush.position = brushPos;

        //if (!isGamePlaying)
        //    return;

        //FTimeTool.Record("On Fill");

        int x, y;
        float rate = 1.5f;
        if (Vector3.Distance(brushPos, m_prevousBrushPoint) > rate)
        {
            Vector3 dir = brushPos - m_prevousBrushPoint;
            Vector3 addDir = dir.normalized * rate;
            while (addDir.magnitude <= dir.magnitude)
            {
                _Brush.position = m_prevousBrushPoint + addDir;
                if (GetInputUV(_Brush.anchoredPosition, out x, out y))
                {
                    DrawTexture(x, y);
                }
                addDir += dir.normalized * rate;
            }
        }
        _Brush.position = brushPos;
        if (GetInputUV(_Brush.anchoredPosition, out x, out y))
        {
            if (!isBrushing)
            {
                isBrushing = true;
                m_brushAudio = this.PlayAudioEx(StudyAudioName.t_41003, true);

            }

            DrawTexture(x, y);
        }
        else
        {
            if (isBrushing)
            {
                isBrushing = false;
                if (m_brushAudio != null)
                {
                    m_brushAudio.Stop();
                    m_brushAudio = null;
                }
            }
        }
        m_prevousBrushPoint = _Brush.position;

        //FTimeTool.Record("On Fill");
    }

    private void OnUp()
    {
        CheckIsFillAll();

        isBrushing = false;
        isStartDragBrush = false;
        if (m_brushAudio != null)
        {
            m_brushAudio.Stop();
            m_brushAudio = null;
        }
    }

    private void OnBrushDown()
    {
        Vector3 to = FUGUITool.ScreenPointToUGUIPoint(WindowManager.Instance.canvas, Input.mousePosition);
        m_dragOffset = _Brush.position - to;
        m_prevousBrushPoint = _Brush.position;
        isStartDragBrush = true;
    }

    private void StartFillTexture(Texture2D fillTexture, Color fillColor, System.Action onCompleteCallback)
    {
        onFillCompleteCallback = onCompleteCallback;
        m_fillTex = fillTexture;
        m_fillColor = fillColor;
        isGamePlaying = true;

        int width = m_fillTex.width;
        int height = m_fillTex.height;

        m_drawTex = null;
        m_drawTex = new Texture2D(width, height);
        m_drawTex.SetPixels(m_fillTex.GetPixels());
        m_drawTex.Apply(false);

        m_drawInfo = new bool[width, height];
        float val = 0.35f;
        for (int i = 0; i < width; i++)
        {
            for (int j = 0; j < height; j++)
            {
                Color col = m_drawTex.GetPixel(i, j);
                if (col.r > val && col.g > val && col.b > val && col.a > val)
                {
                    m_drawInfo[i, j] = true;
                    currentTotalPixelNeedToFill++;
                }
                else
                    m_drawInfo[i, j] = false;
            }
        }

        _Brush.gameObject.SetActive(true);
        _BrushColor.color = fillColor;
        _FillTexture.gameObject.SetActive(true);
        _FillTexture.transform.localScale = Vector3.one;
        _FillTexture.rectTransform.anchoredPosition = m_fillTextureStartPos;
        _FillTexture.texture = m_drawTex;
        _FillTexture.SetNativeSize();
        m_originPoint = _FillTexture.rectTransform.anchoredPosition - new Vector2(m_drawTex.width, m_drawTex.height) / 2;
    }

    private bool GetInputUV(Vector2 brushAnchorPos, out int x, out int y)
    {
        Vector2 dir = brushAnchorPos - m_originPoint;
        x = (int)dir.x;
        y = (int)dir.y;

        if (x < 0 || y < 0 || x > m_drawTex.width || y > m_drawTex.height)
            return false;

        return true;
    }

    private void DrawTexture(int draw_x, int draw_y)
    {
        int texWidth = m_drawTex.width;
        int texHeight= m_drawTex.height;
        
        int stX = Mathf.Clamp(draw_x - halfBrushTexWidth, 0, texWidth);
        int stY = Mathf.Clamp(draw_y - halfBrushTexHeight, 0, texHeight);
        int endX = Mathf.Clamp(draw_x + halfBrushTexWidth, 0, texWidth);
        int endY = Mathf.Clamp(draw_y + halfBrushTexHeight, 0, texHeight);

        int offsetX = Mathf.Abs(draw_x - halfBrushTexWidth);
        int offsetY = Mathf.Abs(draw_y - halfBrushTexHeight);
        for (int x = stX; x < endX; x++)
        {
            for (int y = stY; y < endY; y++)
            {
                if (IsBrushDraw(x - offsetX, y - offsetY))
                {
                    if (m_drawInfo[x, y])
                    {
                        Color col = m_drawTex.GetPixel(x, y);
                        m_drawTex.SetPixel(x, y, Color.Lerp(col, m_fillColor, col.a));
                        m_drawInfo[x, y] = false;
                    }
                    //Color col = m_drawTex.GetPixel(x, y);
                    //if (col.r > 0.5f && col.g > 0.5f && col.b > 0.5f && col.a > 0.5f)
                    //{
                    //    m_drawTex.SetPixel(x, y, Color.Lerp(col, m_fillColor, col.a));
                    //}
                }
            }
        }

        m_drawTex.Apply(false);
    }

    private bool IsBrushDraw(int x, int y)
    {
        if (x < 0 || y < 0 || m_brushTex.width <= x || m_brushTex.height <= y)
            return false;
        return m_brushInfo[x, y];
        //Color col = m_brushTex.GetPixel(x, y);
        //return col.a > 0.2f;
    }

    private void CheckIsFillAll()
    {
        int texWidth = m_drawTex.width;
        int texHeight = m_drawTex.height;

        int stX = 0;
        int stY = 0;
        int endX = texWidth;
        int endY = texHeight;

        int count = 0;
        for (int x = stX; x < endX; x++)
        {
            for (int y = stY; y < endY; y++)
            {
                if (m_drawInfo[x, y])
                    count++;
            }
        }

        float completePixelThreld = currentTotalPixelNeedToFill * (1 - float.Parse(m_info.texFillCompleteThrehold) / 100);
        //Debug.Log("count: " + count + "threld: " + completePixelThreld);
        if (count < completePixelThreld)
        {
            m_drawTex.Apply(true);
            OnFillComplete();
        }

    }

    private void OnFillComplete()
    {
        if (isGamePlaying)
        {
            currentTotalPixelNeedToFill = 0;
            this.PlayAudioEx(StudyAudioName.t_41004);
            isGamePlaying = false;
            if (onFillCompleteCallback != null)
                onFillCompleteCallback();
        }
    }


    #region uievent

    private void OnButtonReturnClick()
    {
        if (isLockInput)
            return;
        isLockInput = true;

        EnglishColorManager.Instance.StopCurrentGame();
        //WindowManager.Instance.CloseWindow(WinNames.FillColorGamePanel);
    }

    private void OnButtonLoudSpeakerClick()
    {
        isSpeakerRepeat = true;
    }

    #endregion



    public void StartGame(EnglishColoursInfo info, System.Action<bool> callback)
    {
        if (info == null)
        {
            Debug.LogError("Fill info is null!");
            if (callback != null)
                callback(false);
            return;
        }
        //Debug.LogError("----------------- StartGame");

        m_info = info;
        completeCallback = callback;
        isLockInput = false;
        _ReadPanel.SetActive(false);
        _ColorImage1.gameObject.SetActive(false);
        _ColorImage2.gameObject.SetActive(false);
        _Brush.SetActive(true);
        _Brush.anchoredPosition = m_brushStartPos;

        _WordShowPanel.SetActive(true);

        Color filledColor = m_info.fillColor.ConvertToColor();
        _LULetter.sprite = UISpriteManager.Instance.GetSprite(emUIAltas.English_Colours, m_info.ColorTexName.ToLower());
        _LULetter.SetNativeSize();
        _BTText.gameObject.SetActive(true);
        _BTText.text = m_info.mainTexAudioWord;

        FillTextureFirst();
    }

    // 开始第一次填充
    private void FillTextureFirst()
    {

        GameAudioSource audio = this.PlayEnglishColoursAudioEx(m_info.mainTexAudio);
        StartFillTexture(LoadTexture(m_info.mainTex), m_info.fillColor.ConvertToColor(), ()=> {

            _Effect_Suc.SetActive(true);
            _BTText.gameObject.SetActive(false);
            GameAudioSource audio1 = this.PlayEnglishColoursAudioEx(m_info.mainTexWordAudio);
            this.AddTimerEx(audio1.Length + 1f, () => {

                _Effect_Suc.SetActive(false);
                float duration = 1f;
                _FillTexture.transform.DOScale(_ColorImage1.transform.localScale, duration).SetEase(Ease.Linear);
                _FillTexture.transform.DOMove(_ColorImage1.transform.position, duration).SetEase(Ease.Linear).OnComplete(() =>
                {
                    _ColorImage1.gameObject.SetActive(true);
                    _ColorImage1.texture = _FillTexture.texture;
                    _ColorImage1.SetNativeSize();
                    _FillTexture.gameObject.SetActive(false);
                    FillRandomTexture();
                    //_FillTexture.transform.localScale = Vector3.one;
                    //_FillTexture.rectTransform.anchoredPosition = m_fillTextureStartPos;
                });

                this.PlayAudioEx(StudyAudioName.t_41005);
            });
        });
    }

    // 开始随机填充
    private void FillRandomTexture()
    {
        string[] texArr = m_info.randomTex.Split(';');
        int index = Random.Range(0, texArr.Length);

        float time = 1;
        string[] audioArr = m_info.randomTexAudio.Split(';');
        if (audioArr.Length == texArr.Length)
        {
            GameAudioSource audio = this.PlayEnglishColoursAudioEx(audioArr[index]);
            time += audio.Length;
        }

        string[] wordArr = m_info.randomTexAudioWord.Split(';');
        _BTText.text = wordArr[index];
        _BTText.gameObject.SetActive(true);
        StartFillTexture(LoadTexture(texArr[index]), m_fillColor, () =>
        {
            _Effect_Suc.SetActive(true);
            _BTText.gameObject.SetActive(false);
            string[] audioTexArr = m_info.randomTexWordAudio.Split(';');
            GameAudioSource audio1 = this.PlayEnglishColoursAudioEx(audioTexArr[index]);
            this.AddTimerEx(audio1.Length + +1f, () => {

                _Effect_Suc.SetActive(false);
                float duration = 1f;
                _FillTexture.transform.DOScale(_ColorImage2.transform.localScale, duration).SetEase(Ease.Linear);
                _FillTexture.transform.DOMove(_ColorImage2.transform.position, duration).SetEase(Ease.Linear).OnComplete(() =>
                {
                    _ColorImage2.gameObject.SetActive(true);
                    _ColorImage2.texture = _FillTexture.texture;
                    _ColorImage2.SetNativeSize();
                    _FillTexture.gameObject.SetActive(false);
                    _FillTexture.rectTransform.anchoredPosition = m_fillTextureStartPos;

                    PlayWordAudio();
                });

                this.PlayAudioEx(StudyAudioName.t_41005);
            });
        });
    }

    private void PlayWordAudio()
    {
        _ReadPanel.SetActive(true);
        _Brush.SetActive(false);
        isSpeakerRepeat = false;
        _WordText.text = m_info.word;
        _WordText.color = m_info.SpecialColor.ConvertToColor();

        string[] audioArr = m_info.wordAudio.Split(';');
        PlayAudioArray(audioArr, 0, 1.0f, () => {

            Debug.LogError("关卡结束");
            if (completeCallback != null)
                completeCallback(true);
        });

    }

    private void PlayAudioArray(string[] audioArr, int index, float intervalTime, System.Action callback)
    {
        if (index >= audioArr.Length)
        {
            if (callback != null)
                callback();
            return;
        }

        GameAudioSource audio = this.PlayEnglishColoursAudioEx(audioArr[index]);
        this.AddTimerEx(audio.Length + intervalTime, () => {
            if (isSpeakerRepeat)
            {
                isSpeakerRepeat = false;
            }
            else
            {
                index++;
            }
            PlayAudioArray(audioArr, index, intervalTime, callback);
        });

    }



    private Texture2D LoadTexture(string name)
    {
        Texture2D tex = Res.LoadTexture2D(TEXTURE_BASE_PATH + name);
        if (tex == null)
        {
            Debug.LogError("Load texture2d error! path: " + TEXTURE_BASE_PATH + name);
        }
        return tex;
    }



}
